/*!
 * Copyright (c)2007-2009, stauren.net
 * @file popup.js
 * @class __.widget.Popup
 * @author <a href="mailto:stauren@stauren.net">stauren</a>
 * @revision:
 */

__.set("__.widget");
__.log('Popup: Class begin.');
(function() {
  var  _config = {
    cls : {
      frame: 'du-popup-container',
      content : 'du-popup-content',
      hidden : 'du-popup-hidden',
      close : 'du-popup-close',
      closeCtn : 'du-popup-closectn',
      closed : 'du-popup-closed',
      cancel: 'du-popup-cancel',
      ok : 'du-popup-ok',
      hbf: 'du-popup-hbf',
      hd : 'du-popup-hd',
      bd : 'du-popup-bd',
      ft : 'du-popup-ft'
    },
    sGlobalPrefix : 'Popup',
    sOk: 'OK',
    sCancel : 'Cancel',
    sCssSpriteSrc : 'http://localhost/att/workspace/os/svn/trunk/src/popup/bg.png',
    //sCssSpriteSrc : 'http://maps.google.com/intl/en_ALL/mapfiles/iw3.png',
    //sCssSpriteSrc : 'http://k.kbcdn.com/global/popup/bg.png',
    //sCssSpriteIe6Src : 'http://maps.google.com/intl/en_ALL/mapfiles/iw3.png',
    sCssSpriteIe6Src: 'http://localhost/att/workspace/os/svn/trunk/src/popup/bg.png',
    //sCssSpriteIe6Src : 'http://k.kbcdn.com/global/popup/bg.gif',
    defInstCfg : {
      bUniqueMode : false,
      bCenter : true,
      bModal : true,
      bAutoAdjust : true,
      iTop : 0,
      iLeft : 0,
      iWidth : 400,
      iHeight : 300,
      vContent : '',
      bShowAfterInit : true
    }
  };

  if (__.config.ua.ie == 6) {
    _config.sCssSpriteSrc = _config.sCssSpriteIe6Src;
  }

  var _ = __._;

  /**#@+
   * the private functions
   * @private
   * @memberOf __.widget.Popup
   */
   
  /**
   * simple log function used in class
   * @param {mixed} t anything to be logged
   */
  var _log = function(t) {
    _.log(_config.sGlobalPrefix +': '+ t);
  };

  /**
   * get existing or create frame
   */
  var _getFrame = function(that) {
    if (!that._config.bUniqueMode) {
      var frames = _findExistingFrame();
      var id = _.find(frames, function(o) {
        if (_.hasClass(o, _config.cls.closed)) {
          return true;
        }
      });
      if (id >= 0) {
        return _purgeFrame(frames[id]);
      }
    }
    return _createFrame(that);
  };

  /**
   * find all existing frames
   */
  var _findExistingFrame = function() {
    return _.$('div.'+ _config.cls.frame);
  };

  /**
   * clear an existing frame
   */
  var _purgeFrame = function(fr) {
    return fr;
  };

  /**
   * create a popup frame
   */
  var _createFrame = function(that) {
    var w = that._config.iWidth, h = that._config.iHeight,
    isIe6 = __.config.ua.ie == 6,
    hd = that._config.sTitle ? {
      cls : _config.cls.hd, css : 'border-bottom:2px solid #E1E8F2;', child : {
        tag : 'h3', css : 'font-size:16px;padding:0 0 2px 10px;font-weight:bold;', text : that._config.sTitle
      }
    } : {},
    bd = { cls : _config.cls.bd, css:'padding:6px;'},
    yes = that._config.onOk !== false ? '' : 'display:none;',
    no = that._config.onCancel !== false ? '' : 'display:none;',
    close = that._config.onClose !== false ? '' : 'display:none;',
    ie6filter = isIe6 ? 'filter:alpha(opacity=65);' : '',
    corner = {
      css : 'width:25px;height:25px;overflow:hidden;position:absolute;', child : {
        tag : 'img', src : _config.sCssSpriteSrc, css : 'position:absolute;-moz-user-select:none;cursor:move;'+ ie6filter
      }
    }, corners = [], xmid1 = {
      css : 'width:'+(w - 40)+'px;height:20px;overflow:hidden;position:absolute;left:20px;', child : {
        tag : 'img', src : _config.sCssSpriteSrc, css : 'position:absolute;left:-20px;-moz-user-select:none;cursor:move;'+ ie6filter
      }
    }, xmid2, ymid1 = {
      css : 'width:20px;height:'+(h-40)+'px;overflow:hidden;position:absolute;top:20px;background:transparent url('+_config.sCssSpriteSrc+') repeat-y 0 -20px;-moz-user-select:none;cursor:move;'+ ie6filter
    }, ymid2;

    for (var i=0, newobj;i<4;i++) {
      corners[corners.length] = _.clone(corner);
    }
    corners[0].css += 'top:0;left:0;';
    corners[0].child.css += 'top:0;left:0;';
    corners[1].css += 'top:0;right:0px;';
    corners[1].child.css += 'top:0;left:-665px;';
    corners[2].css += 'bottom:0;left:0;';
    corners[2].child.css += 'top:-665px;left:0;';
    corners[3].css += 'bottom:0;right:0px;';
    corners[3].child.css += 'top:-665px;left:-665px;';

    xmid2 = _.clone(xmid1);
    xmid1.css += 'top:0;';
    xmid1.child.css += 'top:0;';
    xmid2.css += 'bottom:0px;';
    xmid2.child.css += 'top:-670px;';

    ymid2 = _.clone(ymid1);
    ymid1.css += 'left:0;';
    ymid2.css += 'right:0;background-position:-670px -20px;';


    var fr = _.addEl({
      cls : _config.cls.frame, css : 'position:absolute;width:'+ w +'px;height:'+ h +'px;display:none;', child : [{
        cls : _config.cls.content, css : 'position:relative;width:'+ (w-20) +'px;height:'+ (h-20) +'px;top:10px;left:10px;', child : {
          cls : _config.cls.hbf, css : 'position:absolute;top:0px;left:0px;width:'+ (w - 20) +'px;height:'+ (h - 20) +'px;background:#fff;text-align:left;z-index:10;', child : [
            hd,
            bd,
            {
            cls : _config.cls.ft, css : 'position:absolute;bottom:0px;right:0px;', child : [{
              tag : 'a', href : '#', css :'margin-right:10px;text-decoration:underline;'+ yes, cls : ['yk-btn', 'yk-btn-style-b', 'yk-m', _config.cls.ok], child : {
                tag : 'b', css : 'color:#333;', text : _config.sOk
              }
            }, {
              tag : 'a', href : '#', css :'margin-right:10px;text-decoration:underline;'+ no, cls : ['yk-btn', 'yk-btn-style-c', 'yk-m', _config.cls.cancel], child : {
                tag : 'b', css : 'color:#333;', text : _config.sCancel 
              }
            }]
          }]
        }
      },
      isIe6 ? {
        tag :'iframe', css:'position:absolute;top:0;left:0;z-index:-1;filter:alpha(opacity=0);width:'+ w + 'px;height:'+ h +'px;'
      } : false,  
      corners[0],
      corners[1],
      corners[2],
      corners[3],
      xmid1,
      xmid2,
      ymid1,
      ymid2,
      {
        cls : _config.cls.closeCtn, css : 'width:14px;height:13px;position:absolute;top:10px;right:10px;'+ close, child : {
          tag :'a', cls : _config.cls.close, href : '#', css : 'height:13px;width:14px;display:block;background:transparent url('+_config.sCssSpriteSrc+') no-repeat -354px -690px;'
        }
      }]
    }, document.body);
    return fr;
  };

  var _updateZindex = function(fr, z) {
    var cl = _config.cls.content, cl2 = _config.cls.closeCtn;
    _.e(_.$('div', fr), function(o) {
      if (o.parentNode === fr) {
        _.setP(o, 'zIndex', _.hasClass(o, cl) || _.hasClass(o, cl2) ? z : z-1);
      }
    });
  };

  /**
   * add drag and drop event for frame
   */
  var _addDdEvent = function(obj) {
    var ctn = obj.frame,
    hbf = _.f('.'+ _config.cls.hbf, obj.frame),
    hl = function(e) {
      var t = _.getTarget(e);
      if (!_.isAncestor(hbf, t)) {
        _.beginDrag(e, obj.frame, !__.config.ua.ie);
      }
      return false;
    }, ary = [ctn, 'mousedown', hl];

    obj._events['draganddrop'] = ary;
    _.on.apply(_, ary);
  };

  /**
   * add drag and drop event for frame
   */
  var _addClickEvent = function(obj) {
    //obj._events['draganddrop'] = ary;
    //_.on.apply(_, ary);
    var ye = obj._events, yy = ye.yui, fr = obj.frame, ce = YAHOO.util.CustomEvent,
    drs = {
      Ok : _.f('a.'+ _config.cls.ok, fr),
      Cancel : _.f('a.'+ _config.cls.cancel, fr),
      Close : _.f('a.'+ _config.cls.close, fr)
    };

    yy['onOk'] = new ce('onOk');
    yy['onCancel'] = new ce('onCancel');
    yy['onClose'] = new ce('onClose');

    var hl = function(e) {
      var t = _.getTarget(e),
      type = _.find(drs, function(o) {
        return o===t || _.isAncestor(o, t);
      }, true);
      type !== -1 && yy['on'+ type].fire(obj);
    }, ary = [fr, 'click', hl];

    ye['onClick'] = ary;
    _.on.apply(_, ary);
  };

  /**#@-*/


  __.widget.Popup= __.Class.extend(
  /**
   * @lends __.widget.Popup.prototype
   */
  {

    /**
     * the iv div is showing or not
     * @memberOf __.widget.Popup
     * @type boolean 
     */
    ivDiv : false,

    /**
     * frame root dom reference
     * @memberOf __.widget.Popup
     * @type object
     */
    frame : null,

    /**
     * body dom reference
     * @memberOf __.widget.Popup
     * @type object
     */
    body : null,

    /**
     * events objects, used for purge
     * @memberOf __.widget.Popup
     * @private
     * @typea object 
     */
    _events : {},

    /**
     * the constructor of popup window
     * @constructs
     * @param {string|dom|object} content popup content, could be innerHTML or dom refence or __._.addEl parameter object
     * @param {string} title popup title, this param could be omitted
     * @param {object} config detail config object, the last param is config
     * @config {function} onOk handler when ok button is clicked, receive an param of the Popup object
     * @config {function} onCancel handler when ok button is clicked, receive an param of the Popup object
     * @config {function} onClose handler when ok button is clicked, receive an param of the Popup object
     * @config {boolean} bModal this is a modal dialog or not
     */
    init : function(content) {
      var config = arguments[arguments.length - 1];
      config = typeof config == 'object' ? config : {};
      config.vContent = content || undefined;
      if (typeof arguments[1] == 'string') {
        config.sTitle = arguments[1];
      }
      this._config = _.clone(_config.defInstCfg);
      __.objExtend(this._config, config);

      this.frame = _getFrame(this);
      if (!this.frame) {
        throw new Error('Popup: fail to get frame.');
      }

      this.body = _.f('.'+ _config.cls.bd, this.frame);
      this.setContent(this._config.vContent, false);
      
      this._preLoadBg();
      //this._setPosition();
      this._addEvents();
      this._config.bShowAfterInit && this.show();
      _log('Class initiated');
    }
    ,

    /**
     * all d&d and click events
     * @private
     * @memberOf __.widget.Popup
     */
    _addEvents : function() {
      var ey = this._events['yui'] = {};
      _addClickEvent(this);
      _addDdEvent(this);
      ey.onOk.subscribe(function() {
        var that = arguments[1][0];
        that.hide();
        that._config.onOk && that._config.onOk.call(window, that);
      });
      ey.onCancel.subscribe(function() {
        var that = arguments[1][0];
        that.hide();
        that._config.onCancel && that._config.onCancel.call(window, that);
      });
      ey.onClose.subscribe(function() {
        var that = arguments[1][0];
        that.hide();
        that._config.onClose && that._config.onClose.call(window, that);
      });
    }
    ,

    /**
     * set the position of popup frame
     * @private
     * @memberOf __.widget.Popup
     * @param {array} position x,y of popout position
     */
    _setPosition : function(position) {
      if (_.isArray(position)) {
        _.setElXY(this.frame, position);
      } else if (this._config.bCenter) {
        _.setCenter(this.frame);
      } else {
        _.setElXY(this.frame, [this._config.iLeft, this._config.iTop]);
      }
    }
    ,

    /**
     * set the size of popup frame
     * @memberOf __.widget.Popup
     */
    setSize : function(w, h) {
      var el = this.body, fr = this.frame, sw = function(el, w) {
        el.style.width = w +'px';
      }, sh = function(el, h) {
        el.style.height = h +'px';
      }, sl = function(el, l) {
        el.style.left = h +'px';
      };
      if (!_.isInt(w) || !_.isInt(h)) {
        w = el.offsetWidth || el.clientWidth || parseInt(el.style.width);
        h = el.offsetHeight || el.clientHeight || parseInt(el.style.height);
        if (_.isInt(w) && _.isInt(w)) {
          //40 = frame border
          w += 20;
          h += 20;
          //25 = ft button height
          if (this._config.onOk !== false || this._config.onCancel !== false ) {
            h += 25;
          }
        }
      }
      if (_.isInt(w) && _.isInt(w)) {
        sw(fr, w);
        sh(fr, h);
        sw(fr.firstChild, w - 20);//popup-content
        sh(fr.firstChild, h - 20);
        sw(fr.firstChild.firstChild, w - 20);//popup-hbf
        sh(fr.firstChild.firstChild, h - 20);
        //40 = frame border width
        sw(fr.childNodes[5], w - 40);
        sw(fr.childNodes[6], w - 40);
        sh(fr.childNodes[7], h - 40);
        sh(fr.childNodes[8], h - 40);
      }
    }
    ,

    /**
     * add or remove the iv div
     * @private
     * @memberOf __.widget.Popup
     * @param {boolean} show true to show the iv div
     */
    _toggleIvDiv : function(show) {
      if (this._config.bModal) {
        !this.ivDiv && show && _.addIvDiv();
        this.ivDiv && !show && _.remIvDiv();
        this.ivDiv = show;
      }
    }
    ,

    /**
     * preload the background image and get its size
     * @private
     * @memberOf __.widget.Popup
     */
    _preLoadBg : function() {
      var a = new Image();
      /*_.on(a, 'load', function() {
      });*/
      a.src = _config.sCssSpriteSrc;
    }
    ,

    /**
     * show the pop div, append it if not already done
     * @memberOf __.widget.Popup
     * @param {array} position x,y of popout position
     */
    show : function(position) {
      this._toggleIvDiv(true);
      var z = parseInt(_.getP(this.frame, 'zIndex'));
      if (isNaN(z) || z <= __.topLayer) {
        _.setP(this.frame, 'zIndex', ++__.topLayer);
        __.topLayer += 2;
        _updateZindex(this.frame, __.topLayer);
      }

      _.setP(this.frame, 'display', 'block');
      this._config.bAutoAdjust && this.setSize();
      this._setPosition(position);
    }
    ,

    /**
     * set the content of the popup frame
     * @param {string|object|node} ct
     * @param {boolean} doadjust
     * @memberOf __.widget.Popup
     */
    setContent: function(ct, doadjust) {
      doadjust = doadjust === false ? false : true;
      if (_.isString(ct)) {
        this.body.innerHTML = ct;
      } else if (_.isNode(ct)) {
        this.body.appendChild(ct);
      } else if (_.isObject(ct)) {
        _.addEl(ct, this.body);
      }
      doadjust && this._config.bAutoAdjust && this.setSize();
    }
    ,

    /**
     * set the content of the popup frame
     * @param {object} config
     * @config {function} onOk handler when ok button is clicked, receive an param of the Popup object
     * @config {function} onCancel handler when ok button is clicked, receive an param of the Popup object
     * @config {function} onClose handler when ok button is clicked, receive an param of the Popup object
     * @memberOf __.widget.Popup
     */
    setHandler : function(config) {
      var c = this._config;
      c.onOk = config.onOk || c.onOk;
      c.onCancel = config.onCancel || c.onCancel;
      c.onClose = config.onClose || c.onClose;
    }
    ,

    /**
     * hide the pop div
     * @memberOf __.widget.Popup
     */
    hide : function() {
      this._toggleIvDiv(false);
      _.setP(this.frame, 'display', 'none');
    }
    ,

    /**
     * close and purge the frame (can't show the same content again)
     * the frame will be hidden and left for possible future use
     * @memberOf __.widget.Popup
     */
    close : function() {
      _.addClass(this.frame, _config.cls.closed);
      this.setContent('');
      this.hide();
    }
  });

  _.addStyle('\
.yk-popup-close {\
  background:transparent url('+ _config.sCssSpriteSrc +') no-repeat 0px -50px;\
}\
.yk-popup-close:hover {\
  background-position : -40px -50px;\
}\
');

})();
__.log('Popup: Class end.');
